<template>
  <view class="genealogy-generation">
    <!-- 当前代节点 -->
    <view
      :class="[
        'tree-node',
        `highForce-${person.id}`,
        { highlighted: person.id === searchId },
        { UnAlive: person.alive == 0 },
      ]"
      :id="'highForce-' + person.id"
      :style="{ left: nodeX + 'px', top: nodeY + 'px' }"
      @click="$emit('node-click', person)"
    >
      <view
        class="node-card"
        :class="{ male: person.gender === 1, female: person.gender === 0 || person.gender === 2 }"
        @click.stop="onNodeCardClick"
      >
        <view class="avatar-container">
          <image
            v-if="person.photoUrl && !mainImageError"
            :src="person.photoUrl"
            class="avatar"
            mode="aspectFill"
            @error="handleMainImageError"
          />
          <template v-else>
            <image
              v-if="person.gender === 1 || person.gender === 0 || person.gender === 2"
              :src="person.gender === 1 ? defaultAvatarUrlMen : defaultAvatarUrlWomen"
              class="avatar"
              mode="aspectFill"
            />
            <text v-else class="avatar-text">{{ getAvatarText(person) }}</text>
          </template>
        </view>
        <view class="node-info">
          <text class="node-name">{{ person.firstName }}{{ person.lastName }}</text>
          <text v-if="person.remark" class="node-generation">{{ person.remark }}</text>
          <text v-if="person.level != 0" class="node-generation">{{ person.level }}世</text>
          <view v-if="person.fromAncestor" class="node-jizu">
            <text>{{ person.fromAncestor }}第{{ person.level1 }}代</text>
          </view>
        </view>
      </view>
      <!-- 移除内部菜单，改为在tree.vue中处理 -->

      <!-- 添加缩/展按钮 -->
      <view
        v-if="person.children && person.children.length > 0"
        class="toggle-children"
        :style="{ left: '50%', top: '100%', transform: 'translateX(-50%)', marginTop: '15px' }"
        @click.stop="toggleChildren"
      >
        {{ isChildrenVisible ? "缩" : "展" }}
      </view>
    </view>

    <!-- 配偶节点 -->
    <template v-if="person.spouseList && person.spouseList.length > 0">
      <view
        v-for="(spouse, spouseIdx) in person.spouseList"
        :key="`spouse-${level}-${index}-${spouseIdx}`"
        :class="[
          'tree-node',
          `highForce-${spouse.id}`,
          { highlighted: spouse.id === searchId },
          { UnAlive: spouse.alive == 0 },
        ]"
        :id="'highForce-' + spouse.id"
        :style="{ left: `${spouseX(spouseIdx)}px`, top: `${nodeY}px` }"
        @click="$emit('node-click', spouse)"
      >
        <view
          class="node-card"
          :class="{ male: spouse.gender === 1, female: spouse.gender === 0 || spouse.gender === 2 }"
          @click.stop="(e) => onSpouseCardClick(spouse, e)"
        >
          <view class="avatar-container">
            <image
              v-if="spouse.photoUrl && !imageError"
              :src="spouse.photoUrl"
              class="avatar"
              mode="aspectFill"
              @error="handleImageError"
            />
            <image v-else :src="defaultAvatarUrlWomen" class="avatar" mode="aspectFill" />
          </view>
          <view class="node-info">
            <text class="node-name">{{ spouse.firstName }}{{ spouse.lastName }}</text>
            <text v-if="spouse.remark" class="node-generation">{{ spouse.remark }}</text>
            <text v-else class="node-generation">配偶</text>
            <text class="node-generation">{{ person.level }}世</text>
            <view v-if="person.level1" class="node-jizu">
              <text>{{ person.fromAncestor }}第{{ person.level1 }}代</text>
            </view>
          </view>
        </view>
        <!-- 移除配偶节点内部菜单，改为在tree.vue中处理 -->
      </view>

      <!-- 连接线 -->
      <view
        class="connector-line"
        :style="{
          left: `${connectorX}px`,
          top: `${connectorY}px`,
          width: `${spouseConnectorWidth}px`,
          height: '1px',
        }"
      ></view>
      <!-- 心形 (每个配偶一个) -->
      <view
        v-if="person.spouseList.length > 0"
        :key="`heart-${level}-${index}-0`"
        class="heart-icon"
        :style="{ left: `${heartX(0)}px`, top: `${heartY}px` }"
      >
        ❤
      </view>
    </template>

    <!-- 到下一代的连接线 -->
    <template v-if="person.children && person.children.length > 0">
      <!-- 父节点到底部的竖线 -->
      <view>
        <view
          class="connector-line vertical"
          :style="{
            left: `${parentVerticalLineX}px`,
            top: `${nodeY + 180}px`,
            height: `${parentToChildrenLineHeight}px`,
            zIndex: 9999,
          }"
        ></view>
        <view v-if="isChildrenVisible">
          <!-- 渲染横向线（当有多个子节点时） -->
          <view
            v-if="person.children && person.children.length > 1 && childrenHorizontalLineWidth > 0"
            class="connector-line"
            :style="{
              left: `${childrenHorizontalLineLeft}px`,
              top: `${horizontalConnectorY}px`,
              width: `${childrenHorizontalLineWidth}px`,
              zIndex: 9999,
            }"
            @click="
              console.log('横向线点击', {
                x: childrenHorizontalLineLeft,
                y: horizontalConnectorY,
                width: childrenHorizontalLineWidth,
                childrenCount: person.children.length,
              })
            "
          ></view>
          <!-- 子节点竖线 -->
          <template
            v-for="(child, childIdx) in person.children"
            :key="`child-${level}-${index}-${childIdx}`"
          >
            <view
              class="connector-line vertical"
              :style="{
                left: `${childVerticalLineX(childIdx)}px`,
                top: `${childVerticalLineTop}px`,
                height: `${childVerticalLineHeight}px`,
                zIndex: 9999,
              }"
              @click="
                console.log('子节点竖线点击', {
                  x: childVerticalLineX(childIdx),
                  y: horizontalConnectorY,
                })
              "
            ></view>
            <!-- 递归渲染下一代 -->
            <GenealogyGeneration
              :person="child"
              :generation="generation + 1"
              :level="level + 1"
              :index="childIdx"
              :parent-x="childConnectorX(childIdx)"
              :parent-y="nextGenerationY"
              :search-id="searchId"
              :menuNodeId="menuNodeId"
              @node-click="$emit('node-click', $event)"
              @delete-node="$emit('delete-node', $event)"
              @show-menu="emit('show-menu', $event)"
              @view-info="emit('view-info', $event)"
              @scroll-to-node="emit('scroll-to-node', $event)"
            />
          </template>
        </view>
      </view>
    </template>
  </view>
  <AddChildModal
    v-if="showAddChildModal"
    :visible="showAddChildModal"
    :familyOptions="familyOptions"
    :zibeiOptions="zibeiOptions"
    :genderOptions="genderOptions"
    :aliveOptions="aliveOptions"
    @close="showAddChildModal = false"
    @submit="handleAddChild"
  />
</template>

<script lang="ts" setup>
import { ref, computed, onMounted, onBeforeUnmount, type CSSProperties, watch } from "vue";
import AddChildModal from "./AddChildModal.vue";
import GenealogyGeneration from "./GenealogyGeneration.vue";
// 获取本地缓存的用户信息
const userInfo = computed(() => {
  try {
    const info = uni.getStorageSync("user-info");
    return info;
  } catch (error) {
    console.error("获取用户信息失败:", error);
    return null;
  }
});

// 菜单逻辑移到tree.vue中处理

// 添加控制子节点显示/隐藏的状态
const isChildrenVisible = ref(true);

const imageError = ref(false);
const mainImageError = ref(false);
const defaultAvatarUrlMen = ref("https://boyangli.oss-cn-shanghai.aliyuncs.com/20250930/60f908e9e52c4a9b8368abdf1255364b.jpg");
const defaultAvatarUrlWomen = ref("https://boyangli.oss-cn-shanghai.aliyuncs.com/20250930/b647ba9a62b5481d8a86dc2a9bba0854.jpg");

// 定义接口
interface Person {
  id: string;
  firstName: string;
  lastName: string;
  photoUrl?: string;
  gender: number;
  alive?: number;
  remark?: string;
  spouseList?: Person[];
  children?: Person[];
  parentId?: string; // 新增parentId属性
  fromAncestor: string;
  level: number;
  level1: number;
  flag?: number; // 配偶标识
}

// 定义props
interface Props {
  person: Person;
  generation: number; // 判断当前节点是第几代
  level: number; // 判断当前节点是第几层
  index: number; // 判断当前节点是第几个
  parentX: number; // 判断当前节点的父节点X坐标
  parentY: number; // 判断当前节点的父节点Y坐标
  searchId: String; // 接收搜索ID
  menuNodeId: String; // 父组件传递的菜单节点ID
}
const props = defineProps<Props>();

// 定义事件
const emit = defineEmits<{
  "node-click": [person: Person];
  "add-parent": [person: Person];
  "add-child": [person: Person];
  "view-info": [person: Person];
  "add-spouse": [person: Person];
  "delete-node": [person: Person];
  "show-menu": [personId: string | null]; // 修正事件名和类型
  "scroll-to-node": [nodeId: string]; // 新增滚动到节点事件
}>();

// 切换子节点显示/隐藏
function toggleChildren() {
  isChildrenVisible.value = !isChildrenVisible.value;
}

// 监视 searchId 变化，进行定位
watch(
  () => props.searchId,
  (newId) => {
    if (newId === props.person.id) {
      // 判断是否在小程序环境下
      const isMP = process.env.UNI_PLATFORM === 'mp-weixin';

      console.log(isMP, '是否在小程序环境下')
      if (isMP) {
        // 微信小程序环境下使用 uni.createSelectorQuery，并传入组件实例
        const query = uni.createSelectorQuery();
        console.log(query.select(`#highForce-${props.person.id}`), 11111111);
        return;
          // .boundingClientRect()
          // .exec((res) => {
          //   console.log('滚动到节点:', res);
          //   if (res && res[0]) {
          //     // 在小程序中，我们通过事件通知父组件进行滚动
          //     emit('scroll-to-node', props.person.id);
          //   } else {
          //     console.log('未找到节点元素，尝试通过类名查找');
          //     // 备用方案：使用类名查找
          //     const classQuery = uni.createSelectorQuery();
          //     classQuery.select(`.tree-node.highForce-${props.person.id}`)
          //       .boundingClientRect()
          //       .exec((classRes) => {
          //         console.log('通过类名查找结果:', classRes);
          //         if (classRes && classRes[0]) {
          //           emit('scroll-to-node', props.person.id);
          //         }
          //       });
          //   }
          // });
      } else {
        // H5环境下使用原生方法
        const element = document.querySelector(`.tree-node.highForce-${props.person.id}`);
        if (element) {
          element.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
        }
      }
    }
  }
);

const handleImageError = () => {
  imageError.value = true;
};

const handleMainImageError = () => {
  mainImageError.value = true;
};

// 计算属性(配偶连接线)
const spouseConnectorWidth = computed(() => {
  if (!props.person.spouseList || props.person.spouseList.length === 0) {
    return 0; // 如果没有配偶，则没有连接线
  }
  // 连接线从主节点延伸到最后一个配偶节点
  return 20;
});

// 计算节点位置
const nodeX = computed(() => props.parentX);

const nodeY = computed(() => props.parentY);
const connectorX = computed(() => props.parentX + 100);
const connectorY = computed(() => props.parentY + 90);

const heartX = (spouseIdx: number) => {
  // 爱心放在主节点和第一个配偶之间的中点
  if (spouseIdx === 0) {
    return nodeX.value + 102; // 主节点右侧+10px
  }
  // 多配偶时，放在前一个配偶和当前配偶之间
  return spouseX(spouseIdx - 1) + 102;
};

const heartY = computed(() => props.parentY + 80);
const verticalConnectorY = computed(() => props.parentY + 180);
const horizontalConnectorY = computed(() => nextGenerationY.value - 20); // 距离子辈卡片顶部20px
const nextGenerationY = computed(() => props.parentY + 230); // 父辈底部 + 50px

// 让竖线居中于本层（主节点+配偶节点整体）
const verticalLineX = computed(() => {
  // 本层宽度
  const thisWidth = getSubtreeWidth(props.person);
  // 居中
  return props.parentX + thisWidth / 2;
});

// 计算配偶位置（每个配偶占用200px空间）
const spouseX = (spouseIdx: number) => {
  // 主节点宽度 100px，间距 20px
  // 第一个配偶紧挨主节点右侧
  return nodeX.value + 100 + 20 + spouseIdx * (100 + 20);
};

// 让每个子代的竖线居中于子节点卡片
const childVerticalLineX = (childIdx: number) => {
  if (!props.person.children) return 0;
  // 子节点的中心点 - 直接使用子节点的X坐标加上节点宽度的一半
  const childX = childConnectorX(childIdx);
  // 节点宽度100px，居中
  return childX + 50;
};

// 递归计算某个节点（含其所有子孙）的总宽度
const getSubtreeWidth = (person: Person): number => {
  // 主节点和配偶节点总宽度
  let selfWidth = 100 + (person.spouseList ? person.spouseList.length * (100 + 20) : 0);

  if (!person.children || person.children.length === 0) {
    return selfWidth;
  }
  // 子节点总宽度
  const childrenWidth = person.children.reduce((sum, child) => sum + getSubtreeWidth(child), 0);
  // 取最大值，保证下层不会覆盖上层
  return Math.max(selfWidth, childrenWidth);
};

// 计算每个子节点的X坐标
const childConnectorX = (childIdx: number) => {
  // 如果没有子节点，则返回父节点X坐标
  if (!props.person.children) return props.parentX;

  // 只有一个子节点时，与父节点保持适当距离
  if (props.person.children.length === 1) {
    return nodeX.value; // 与父节点中心对齐，但通过连接线连接
  }

  // 多子节点时，确保第一个子节点与父节点水平距离一致
  if (childIdx === 0) {
    // 第一个子节点与父节点中心对齐，确保T型连接
    return nodeX.value;
  }

  // 其他子节点按原有逻辑计算
  let totalOffset = 0;
  for (let i = 0; i < childIdx; i++) {
    totalOffset += getSubtreeWidth(props.person.children[i]);
  }
  let childrenWidth = 0;
  for (let i = 0; i < props.person.children.length; i++) {
    childrenWidth += getSubtreeWidth(props.person.children[i]);
  }
  const thisWidth = getSubtreeWidth(props.person);
  // 确保子节点组整体居中对齐父节点
  return props.parentX + (thisWidth - childrenWidth) / 2 + totalOffset;
};

// 获取头像显示文字
const getAvatarText = (person: Person) => {
  if (!person) return "?";

  if (person.firstName && person.firstName.length > 0) {
    return person.firstName.charAt(0);
  }

  if (person.lastName && person.lastName.length > 0) {
    return person.lastName.charAt(0);
  }

  return person.gender === 1 ? "男" : person.gender === 0 || person.gender === 2 ? "女" : "?";
};

function onNodeCardClick(event: any) {
  event.stopPropagation(); // 阻止事件冒泡
  // 传递完整的person对象给父组件处理
  emit("node-click", props.person);
}

function onSpouseCardClick(spouse: Person, event: any) {
  event.stopPropagation(); // 阻止事件冒泡
  // 传递完整的spouse对象给父组件处理
  emit("node-click", spouse);
}

// function handleClickOutside() {}

// onMounted(() => {
//   document.addEventListener("click", handleClickOutside);
// });

// onBeforeUnmount(() => {
//   document.removeEventListener("click", handleClickOutside);
// });

// 菜单逻辑移到tree.vue中处理

// 菜单样式移到tree.vue中处理

const showAddChildModal = ref(false);
const currentParent = ref<Person | null>(null);

// 选项数据（实际可从接口获取，这里举例写死）
const familyOptions = ref([
  { label: "河间李氏", value: "1" },
  { label: "其他家族", value: "2" },
]);
const zibeiOptions = ref([
  { label: "字辈A", value: "A" },
  { label: "字辈B", value: "B" },
]);
const genderOptions = ref([
  { label: "男", value: 1 },
  { label: "女", value: 0 },
]);
const aliveOptions = ref([
  { label: "在世", value: 1 },
  { label: "已故", value: 0 },
]);

function onAddSpouse(person: Person) {
  uni.navigateTo({
    url: `/pages/genealogy/person/add-spouse?parentId=${person.id}`,
  });
}

// 编辑配偶信息
function onEditSpouse(spouse: Person) {
  uni.navigateTo({
    url: `/pages/genealogy/person/add-spouse?id=${spouse.id}&parentId=${spouse.parentId}&mode=edit&flag=${spouse.flag || 0}`,
  });
}
function onAddParent(person: Person) {
  uni.navigateTo({
    url: `/pages/genealogy/person/add-parent?childId=${person.id}`,
  });
}
function onAddChild(person: Person) {
  uni.navigateTo({
    url: `/pages/genealogy/person/add-child?parentId=${person.id}`,
  });
}

function onEditInfo(person: Person) {
  uni.navigateTo({
    url: `/pages/genealogy/person/edit-node?id=${person.id}&mode=edit`,
  });
}

function handleAddChild(childData: Person) {
  // 这里可以发请求，或直接添加到children
  if (!currentParent.value!.children) currentParent.value!.children = [];
  currentParent.value!.children.push(childData);
  showAddChildModal.value = false;
}

const childrenCount = props.person.children ? props.person.children.length : 0;
const childrenCenters = props.person.children
  ? props.person.children.map((_, idx) => childVerticalLineX(idx))
  : [];
const childrenAreaCenter = computed(() => {
  if (childrenCenters.length === 0) return verticalLineX.value;
  const min = Math.min(...childrenCenters);
  const max = Math.max(...childrenCenters);
  return (min + max) / 2;
});

const childrenHorizontalLineLeft = computed(() => {
  if (!props.person.children || props.person.children.length === 0) return 0;

  // 当只有一个子节点时，横向线应该从父节点竖线延伸到子节点竖线
  if (props.person.children.length === 1) {
    const parentLineX = parentVerticalLineX.value;
    const childLineX = childVerticalLineX(0);
    // 选择较小的X坐标作为起点，确保连接线可见
    return Math.min(parentLineX, childLineX) - 15;
  }

  // 多个子节点时，确保横向线能够连接所有兄弟节点
  const parentCenterX = parentVerticalLineX.value; // 父节点竖线X坐标
  const firstChildX = childVerticalLineX(0);
  const lastChildX = childVerticalLineX(props.person.children.length - 1);

  // 横向线应该从第一个子节点开始，到最后一个子节点结束
  // 确保包含所有兄弟节点的连接点
  const leftBound = Math.min(firstChildX, lastChildX);
  return leftBound;
});

const childrenHorizontalLineWidth = computed(() => {
  if (!props.person.children || props.person.children.length === 0) return 0;

  // 当只有一个子节点时，横向线宽度应该覆盖从父节点竖线到子节点竖线的距离
  if (props.person.children.length === 1) {
    const parentLineX = parentVerticalLineX.value;
    const childLineX = childVerticalLineX(0);
    const distance = Math.abs(childLineX - parentLineX);
    return Math.max(distance + 30, 50); // 确保最小宽度50px，增加额外宽度
  }

  // 多个子节点时，横向线宽度应该覆盖从第一个子节点到最后一个子节点的完整范围
  const firstChildX = childVerticalLineX(0);
  const lastChildX = childVerticalLineX(props.person.children.length - 1);

  // 计算横向线的完整宽度，确保能够连接所有兄弟节点
  const width = Math.abs(lastChildX - firstChildX);
  const minWidth = Math.max(width, 50); // 最小宽度50px，确保好的水平间距

  return minWidth;
});

const verticalLineHeight = computed(() => {
  // 父代竖线高度 = 横向线y - 父节点y
  return horizontalConnectorY.value - nodeY.value + 1; // +1防止像素断裂
});

// 竖线高度 = 横向线y - 竖线起点
const parentToChildrenLineHeight = computed(() => {
  // 父节点竖线起点：父节点底部
  const lineStartY = nodeY.value + 180;

  // 当只有一个子节点时，竖线高度为50px
  if (props.person.children && props.person.children.length === 1) {
    const lineEndY = lineStartY + 50; // 固定高度50px
    return lineEndY - lineStartY;
  }

  // 父节点竖线终点：横向连接线位置
  const lineEndY = horizontalConnectorY.value;
  // 计算高度，确保连线能够正确连接
  const calculatedHeight = lineEndY - lineStartY;
  // 减少最小高度，让连线更紧凑
  const finalHeight = Math.max(calculatedHeight, 30); // 最小高度50px
  return finalHeight;
});

// 父节点竖线X坐标 - 从父节点中心开始，确保水平间距正确
const parentVerticalLineX = computed(() => {
  // 从父节点（李003）的中心开始，确保T型连接
  const x = nodeX.value + 50; // 父节点中心
  return x;
});

// 子节点横向线的中心X坐标 - 确保与父节点竖线对齐
const childrenHorizontalLineCenter = computed(() => {
  if (!props.person.children || props.person.children.length === 0) return nodeX.value + 50;

  // 计算子节点组的中心位置
  const firstChildX = childVerticalLineX(0);
  const lastChildX = childVerticalLineX(props.person.children.length - 1);
  const centerX = (firstChildX + lastChildX) / 2;

  return centerX;
});

// 子节点竖线高度
const childVerticalLineHeight = computed(() => {
  // 当只有一个子节点时，竖线高度需要从父节点竖线结束位置到子节点位置
  if (props.person.children && props.person.children.length === 1) {
    const lineStartY = nodeY.value + 180 + parentToChildrenLineHeight.value;
    const lineEndY = nextGenerationY.value;
    const calculatedHeight = lineEndY - lineStartY;
    // 确保连线能够正确连接到子节点卡片顶部，不插入内部
    return Math.max(calculatedHeight, 0); // 最小高度0px，避免负值
  }
  // 当有多个子节点时，竖线从横向连接线到子节点位置
  const lineStartY = horizontalConnectorY.value;
  const lineEndY = nextGenerationY.value;
  const calculatedHeight = lineEndY - lineStartY;
  return Math.max(calculatedHeight, 0); // 最小高度0px，避免负值
});

// 子节点竖线起始位置
const childVerticalLineTop = computed(() => {
  // 当只有一个子节点时，竖线从父节点竖线结束位置开始
  if (props.person.children && props.person.children.length === 1) {
    return nodeY.value + 180 + parentToChildrenLineHeight.value;
  }
  // 当有多个子节点时，竖线从水平连接线位置开始
  return horizontalConnectorY.value;
});
</script>

<script lang="ts">
export default {
  name: 'GenealogyGeneration'
}
</script>

<style lang="scss" scoped>
.genealogy-generation {
  position: relative;
  overflow: visible;
}

.custom-txt {
  color: black;
  width: 400rpx;
  height: 400rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 40rpx;
  border-radius: 32rpx;
}

/* 节点样式 */
.tree-node {
  position: absolute;
  width: 100px;
  height: 180px;
  border-radius: 16px;
  background: #ffffff;
  z-index: auto;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: visible;

  &.UnAlive {
    .node-card {
      background: #e0e0e0;

      .avatar-container {
        opacity: 0.5;
      }
    }
  }
}

.highlighted {
  transition: all 0.3s ease;

  .node-card {
    background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%) !important;
    border: 2px solid #ffc107;
  }
}

.node-card {
  width: 100%;
  height: 100%;
  border: 2px solid #e9ecef;
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 12px;
  box-sizing: border-box;
  position: relative;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: visible;

  .node-jizu {
    font-size: 11px;
    color: #6c757d;
    text-align: center;
    white-space: normal;
    font-weight: 500;
    width: 130rpx;
  }
}

.node-card.male {
  border-top: 4px solid #007bff;

  &:hover {
    border-top-color: #0056b3;
  }
}

.node-card.female {
  border-top: 4px solid #e91e63;

  &:hover {
    border-top-color: #c2185b;
  }
}

.avatar-container {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 3px solid #dee2e6;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 12px;
  overflow: hidden;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

  &:hover {
    transform: scale(1.05);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }
}

.avatar {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  display: block;
}

.avatar-text {
  font-size: 24px;
  font-weight: 600;
  color: #495057;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.node-info {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.node-name {
  font-size: 13px;
  font-weight: 600;
  color: #212529;
  margin-bottom: 6px;
  text-align: center;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  line-height: 1.2;
}

.node-generation {
  font-size: 11px;
  color: #6c757d;
  margin-bottom: 4px;
  text-align: center;
  font-weight: 500;
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
  padding: 2px 8px;
  border-radius: 10px;
  border: 1px solid #dee2e6;
}

.status-icon {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

.status-icon.alive {
  background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
  border: 2px solid #ffffff;
}

.status-icon.deceased {
  background: linear-gradient(135deg, #6c757d 0%, #495057 100%);
  border: 2px solid #ffffff;
}

/* 连接线样式 */
.connector-line {
  position: absolute;
  background: repeating-linear-gradient(
    90deg,
    #667eea 0px,
    #764ba2 4px,
    transparent 4px,
    transparent 8px
  );
  height: 2px;
  z-index: 1000;
  box-shadow: 0 1px 3px rgba(102, 126, 234, 0.2);
  border-radius: 1px;
  transition: all 0.3s ease;
  opacity: 0.85;

  &:hover {
    background: repeating-linear-gradient(
      90deg,
      #667eea 0px,
      #764ba2 4px,
      transparent 4px,
      transparent 8px
    );
    box-shadow: 0 2px 8px rgba(102, 126, 234, 0.4);
    transform: scaleY(1.2);
    opacity: 1;
  }

  &::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    opacity: 0;
    transition: opacity 0.3s ease;
  }

  &:hover::before {
    opacity: 1;
  }
}

.connector-line.vertical {
  width: 2px;
  background: repeating-linear-gradient(
    180deg,
    #667eea 0px,
    #764ba2 4px,
    transparent 4px,
    transparent 8px
  );
  box-shadow: 1px 0 3px rgba(102, 126, 234, 0.2);
  z-index: 1000;
  border-radius: 1px;
  opacity: 0.85;

  &:hover {
    background: repeating-linear-gradient(
      180deg,
      #667eea 0px,
      #764ba2 4px,
      transparent 4px,
      transparent 8px
    );
    box-shadow: 2px 0 8px rgba(102, 126, 234, 0.4);
    transform: scaleX(1.2);
    opacity: 1;
  }

  &::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    opacity: 0;
    transition: opacity 0.3s ease;
  }

  &:hover::before {
    opacity: 1;
  }
}

.heart-icon {
  position: absolute;
  font-size: 16px;
  color: #e91e63;
  z-index: 1000;
  text-shadow: 0 2px 4px rgba(233, 30, 99, 0.3);
  // animation: heartbeat 2s ease-in-out infinite;
  // @keyframes heartbeat {
  //   0%,
  //   100% {
  //     transform: scale(1);
  //   }
  //   50% {
  //     transform: scale(1.1);
  //   }
  // }
}

.node-menu {
  background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
  border: 1px solid #dee2e6;
  border-radius: 12px;
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.12),
    0 4px 16px rgba(0, 0, 0, 0.08);
  padding: 8px 0;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  backdrop-filter: blur(10px);
  z-index: 999999 !important;
  position: absolute;
  overflow: visible;
  white-space: nowrap;
  word-wrap: break-word;
  word-break: keep-all;
  display: block !important;
  visibility: visible !important;
  opacity: 1 !important;
  clip-path: none !important;
  clip: auto !important;

  &:hover {
    box-shadow:
      0 12px 40px rgba(0, 0, 0, 0.16),
      0 6px 20px rgba(0, 0, 0, 0.12);
  }

  &::before {
    content: "";
    position: absolute;
    top: -10px;
    left: -10px;
    right: -10px;
    bottom: -10px;
    z-index: -1;
  }
}

.menu-item {
  padding: 12px 20px;
  cursor: pointer;
  font-size: 14px;
  color: #495057;
  border-radius: 8px;
  transition: all 0.2s ease;
  font-weight: 500;
  margin: 2px 8px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
  width: calc(100% - 16px);
  box-sizing: border-box;

  &:hover {
    color: #ffffff;
    transform: translateX(2px);
  }

  &:active {
    transform: translateX(2px) scale(0.98);
  }
}

/* 添加的缩/展按钮样式 */
.toggle-children {
  position: absolute;
  width: 24px;
  height: 24px;
  background: #667eea;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-size: 12px;
  font-weight: bold;
  cursor: pointer;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  z-index: 10000;
  transition: all 0.3s ease;

  &:hover {
    background: #764ba2;
    transform: scale(1.1);
  }
}
</style>
